package com.webull.information.center.carwler.task.handler;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.function.Function;

import org.apache.commons.collections.map.LRUMap;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.webull.information.center.carwler.common.model.NewsInformation;
import com.webull.information.center.carwler.common.model.NewsInformation.ArticleClass;
import com.webull.information.center.carwler.common.model.NewsInformation.AssociatesNews;
import com.webull.information.center.carwler.common.util.news.WallStreetCnNewsUitl;
import com.webull.information.center.carwler.common.util.news.WallStreetCnNewsUitl.WallItem;
import com.webull.information.center.carwler.task.support.TikcerNewsProcessor;
import com.webull.information.center.common.constants.Constants;
import com.webull.information.client.model.News;
import com.webull.information.client.model.parm.NewsRelType;

/**
 * 
 * @author smj
 * @Date 2017年7月7日上午9:07:53
 * @version 1.0
 * 
 *          华尔街见闻新闻处理器
 */
@Component
public class WallstreetCnNewsHandler {

	protected final Logger logger = LogManager.getLogger(getClass());
	private static String wall_lang = Constants.lang_zh;// 新浪语言版本
	private @Autowired WallStreetCnNewsUitl wallStreetCnNewsUitl;
	private @Autowired TikcerNewsProcessor tikcerNewsProcessor;

	public void handlerWallstreetCnNews() {

		/*
		 * step1 获取banner页面，当做 frontPage
		 * 
		 */
		List<WallItem> parseTopNewsList = wallStreetCnNewsUitl.parseTopNewsList();
		processWallList(parseTopNewsList);
		/*
		 * step2 获取list列表，当做 frontPage
		 * 
		 */
		List<WallItem> parseHomeNewsList = wallStreetCnNewsUitl.parseHomeNewsList();

		/*
		 * 前两条新闻强制更新
		 */
		for (int i = 0; parseHomeNewsList != null && i < parseHomeNewsList.size() && i < 2; i++) {
			repeatArticle.setFroce(parseHomeNewsList.get(i).getWallId(), true);
		}
		processWallList(parseHomeNewsList);
	}

	public void handlerWallGoldCnNews() {

		/*
		 * step1 获取banner页面，当做 frontPage
		 * 
		 */
		List<WallItem> parseTopNewsList = wallStreetCnNewsUitl.parseGoldTopNewsList();
		processWallList(parseTopNewsList);
		/*
		 * step2 获取list列表，当做 frontPage
		 * 
		 */
		List<WallItem> parseHomeNewsList = wallStreetCnNewsUitl.parseGlodHomeNewsList();

		/*
		 * 前两条新闻强制更新
		 */
		for (int i = 0; parseHomeNewsList != null && i < parseHomeNewsList.size() && i < 2; i++) {
			repeatArticle.setFroce(parseHomeNewsList.get(i).getWallId(), true);
		}
		processWallList(parseHomeNewsList);
	}


	public void processTextReturnAssoc(NewsInformation info0, boolean needAssoc) {
		List<WallItem> assocs = wallStreetCnNewsUitl.addTextReturnAssoc(info0, needAssoc);


		// boolean updateIng =
		// info0.getContent().matches("(?i).*<p>\\s*[^<]{0,8}更新中\\S{0,8}\\s*</p>\\s*$");

		if (StringUtils.isBlank(info0.getContent())) {
			repeatArticle.setFroce(info0.getNote(WallStreetCnNewsUitl.wallId), true); // 下次可以被更新
			return;
		}
	 
		/*
		 * 绑定关联 新闻
		 */
		if (assocs != null)
			for (WallItem item : assocs) {
				AssociatesNews assNews = info0.derivedAssociate();
				bindProperties(item, assNews);
				info0.addAssociatesNews(assNews);
			}
		else
			logger.warn("processTextReturnAssoc assocs is null .url:{}", info0.getUrl());
	}

	private void processWallList(List<WallItem> wallItems) {
		if (wallItems != null)
			for (WallItem item : wallItems) {
				try {
					processWallStreetNews(item);
				} catch (Exception e) {
					logger.error("processWallList wallItems url:{}, error", item.getUrl(), e);
				}
			}

	}

	/**
	 * 绑定属性
	 * 
	 * @param source
	 * @param info
	 */
	private void bindProperties(WallItem source, NewsInformation info) {
		info.setTitle(source.getTitle());
		info.setNewsTime(source.getNewsTime());
		info.setUrl(source.getUrl());
		info.setSourceName(source.getSourceName());
		info.setSummary(source.getSummary());
		info.setHomePage(source.getHomeType());
		info.addMainPic(source.getImg());
		info.setMainProxy(false);
		if (News.HomeType.frontPage.equals(info.getHomePage())) {
			info.getMainPic().setThumSize(450);
		}
		/*
		 * wallId
		 */
		info.setNote(WallStreetCnNewsUitl.wallId, source.getWallId());

		if (repeatArticle.isFroce(source.getWallId())) {
			info.setForceReview(true);
		}
		info.setRegionId(1);
		info.setLanguage(wall_lang);
		info.setCollectSource(News.CollectSource.wallStreet);
		info.setSiteType(News.SiteType.NORMAL);
		info.setArticleClass(ArticleClass.article);
	}


	private void processWallStreetNews(WallItem item) throws Exception {

		NewsInformation info = new NewsInformation();// produce(doc);

		bindProperties(item, info);

		if (!repeatArticle.apply(info.getNote(WallStreetCnNewsUitl.wallId)) //
				|| News.HomeType.frontPage.equals(item.getHomeType())
		) {
			/*
			 * 填充内容和关联新闻
			 */
			tikcerNewsProcessor.bindTargetNewsRecord(info, 0, NewsRelType.homePage);
		}
	}

	private Function2 repeatArticle = new Function2() {
		private LinkedList<String> ids = new LinkedList<>();
		private Map<String, Boolean> needUpdate = new LRUMap(100); // 最大size是100,避免内存 溢出
		@Override
		public Boolean apply(String id) {
			if (ids.contains(id))
				return !isFroce(id);
			// 未重复
			if (ids.size() > 200) {
				String id0 = (String) (((Queue) ids).poll());
				needUpdate.remove(id0);
				ids.add(id);
			}
			return false;
		}

		@Override
		public void setFroce(String id, boolean force) {
			if (force) {
				needUpdate.put(id, true);
			} else {
				if (needUpdate.containsKey(id))
					needUpdate.remove(id);
			}

		}

		@Override
		public boolean isFroce(String id) {
			return needUpdate.getOrDefault(id, false);
		}

	};

	private interface Function2 extends Function<String, Boolean> {
		void setFroce(String id, boolean force);

		boolean isFroce(String id);
	}

}
